diff --git a/web/pgadmin/static/js/keyboard_shortcuts.js b/web/pgadmin/static/js/keyboard_shortcuts.js new file mode 100644 index 0000000..c4a1c5c --- /dev/null +++ b/web/pgadmin/static/js/keyboard_shortcuts.js @@ -0,0 +1,114 @@ +const EDIT_KEY = 71, // Key: G -> Grid values + LEFT_ARROW_KEY = 37, + RIGHT_ARROW_KEY = 39; + +function isMac() { + return window.navigator.platform.search('Mac') != -1; +} + +function isKeyCtrlAlt(event) { + return event.ctrlKey || event.altKey; +} + +function isKeyAltShift(event) { + return event.altKey || event.shiftKey; +} + +function isKeyCtrlShift(event) { + return event.ctrlKey || event.shiftKey; +} + +function isKeyCtrlAltShift(event) { + return event.ctrlKey || event.altKey || event.shiftKey; +} + +function isAltShiftBoth(event) { + return event.altKey && event.shiftKey && !event.ctrlKey; +} + +function isCtrlShiftBoth(event) { + return event.ctrlKey && event.shiftKey && !event.altKey; +} + +function isCtrlAltBoth(event) { + return event.ctrlKey && event.altKey && !event.shiftKey; +} + +function _stopEventPropagation(event) { + event.cancelBubble = true; + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); +} + +/* Debugger: Keyboard Shortcuts handling */ +function keyboardShortcutsDebugger(debuggerController, trans_id, $el, event) { + let keyCode = event.which || event.keyCode; + + // To handle debugger's internal tab navigation like Parameters/Messages... + if (this.isAltShiftBoth(event)) { + // Get the active wcDocker panel from DOM element + let panel_id; + switch(keyCode) { + case LEFT_ARROW_KEY: + this._stopEventPropagation(event); + panel_id = this.getInnerPanel($el, 'left'); + break; + case RIGHT_ARROW_KEY: + this._stopEventPropagation(event); + panel_id = this.getInnerPanel($el, 'right'); + break; + case EDIT_KEY: + this._stopEventPropagation(event); + let panel_content = $el.find( + 'div.wcPanelTabContent:not(".wcPanelTabContentHidden")' + ); + if(panel_content.length) { + let $input = $(panel_content).find('td.editable:first'); + if($input.length) + $input.click(); + } + break; + } + // Actual panel starts with 1 in wcDocker + return panel_id; + } +} + +// Finds the desired panel on which user wants to navigate to +function getInnerPanel($el, direction) { + let total_panels = $el.find('.wcPanelTab'); + // If no panels found OR if single panel + if (!total_panels.length || total_panels.length == 1) + return; + + let active_panel = $(total_panels).filter('.wcPanelTabActive'), + id = parseInt($(active_panel).attr('id')), + fist_panel = 0, + last_panel = total_panels.length - 1; + + // Find desired panel + if (direction == 'left') { + if(id > fist_panel) + id--; + } else { + if (id < last_panel) + id++; + } + return id; +} + +module.exports = { + processEventDebugger: keyboardShortcutsDebugger, + getInnerPanel: getInnerPanel, + // misc functions + _stopEventPropagation: _stopEventPropagation, + isMac: isMac, + isKeyCtrlAlt: isKeyCtrlAlt, + isKeyAltShift: isKeyAltShift, + isKeyCtrlShift: isKeyCtrlShift, + isKeyCtrlAltShift: isKeyCtrlAltShift, + isAltShiftBoth: isAltShiftBoth, + isCtrlShiftBoth: isCtrlShiftBoth, + isCtrlAltBoth: isCtrlAltBoth, +}; diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py index a173c8e..099adb4 100644 --- a/web/pgadmin/tools/debugger/__init__.py +++ b/web/pgadmin/tools/debugger/__init__.py @@ -17,6 +17,8 @@ import random from flask import url_for, Response, render_template, request, session, current_app from flask_babel import gettext from flask_security import login_required +from werkzeug.useragents import UserAgent + from pgadmin.utils import PgAdminModule from pgadmin.utils.ajax import bad_request from pgadmin.utils.ajax import make_json_response, \ @@ -346,6 +348,9 @@ def direct_new(trans_id): if "linux" in _platform: is_linux_platform = True + # We need client OS information to render correct Keyboard shortcuts + user_agent = UserAgent(request.headers.get('User-Agent')) + return render_template( "debugger/direct.html", _=gettext, @@ -354,6 +359,7 @@ def direct_new(trans_id): debug_type=debug_type, is_desktop_mode=current_app.PGADMIN_RUNTIME, is_linux=is_linux_platform, + client_platform=user_agent.platform, stylesheets=[url_for('debugger.static', filename='css/debugger.css')] ) diff --git a/web/pgadmin/tools/debugger/static/js/debugger_ui.js b/web/pgadmin/tools/debugger/static/js/debugger_ui.js index 3a35ceb..f9049d8 100644 --- a/web/pgadmin/tools/debugger/static/js/debugger_ui.js +++ b/web/pgadmin/tools/debugger/static/js/debugger_ui.js @@ -132,7 +132,8 @@ define([ // Variables to store the data sent from sqlite database var func_args_data = this.func_args_data = []; - // As we are not getting pgBrowser.tree when we debug again so tree info will be updated from the server data + // As we are not getting pgBrowser.tree when we debug again + // so tree info will be updated from the server data if (restart_debug == 0) { var t = pgBrowser.tree, i = t.selected(), @@ -501,7 +502,8 @@ define([ } } - // Check if the arguments already available in the sqlite database then we should use the existing arguments + // Check if the arguments already available in the sqlite database + // then we should use the existing arguments if (func_args_data.length == 0) { this.debuggerInputArgsColl = new DebuggerInputArgCollections(my_obj); @@ -537,12 +539,12 @@ define([ setup: function() { return { buttons: [{ - text: 'Debug', + text: gettext('Debug'), key: 13, className: 'btn btn-primary', }, { - text: 'Cancel', + text: gettext('Cancel'), key: 27, className: 'btn btn-primary', }, @@ -563,13 +565,14 @@ define([ }, // Callback functions when click on the buttons of the Alertify dialogs callback: function(e) { - if (e.button.text === 'Debug') { + if (e.button.text === gettext('Debug')) { // Initialize the target once the debug button is clicked and // create asynchronous connection and unique transaction ID var self = this; - // If the debugging is started again then treeInfo is already stored in this.data so we can use the same. + // If the debugging is started again then treeInfo is already + // stored in this.data so we can use the same. if (self.restart_debug == 0) { var t = pgBrowser.tree, i = t.selected(), @@ -791,7 +794,8 @@ define([ }, }); } else { - // If the debugging is started again then we should only set the arguments and start the listener again + // If the debugging is started again then we should only set the + // arguments and start the listener again baseUrl = url_for('debugger.start_listener', { 'trans_id': self.data.trans_id, }); @@ -838,7 +842,7 @@ define([ return true; } - if (e.button.text === 'Cancel') { + if (e.button.text === gettext('Cancel')) { //close the dialog... return false; } @@ -853,8 +857,8 @@ define([ ); /* - If we already have data available in sqlite database then we should enable the debug button otherwise - disable the debug button. + If we already have data available in sqlite database then we should + enable the debug button otherwise disable the debug button. */ if (this.func_args_data.length == 0) { this.__internal.buttons[0].element.disabled = true; @@ -875,7 +879,8 @@ define([ for (var i = 0; i < this.collection.length; i++) { - // TODO: Need to check the "NULL" and "Expression" column value to enable/disable the "Debug" button + // TODO: Need to check the "NULL" and "Expression" column value to + // enable/disable the "Debug" button if (this.collection.models[i].get('value') == '' || this.collection.models[i].get('value') == null || this.collection.models[i].get('value') == undefined) { @@ -899,9 +904,11 @@ define([ }); } - Alertify.debuggerInputArgsDialog('Debugger', args, restart_debug).resizeTo('60%', '60%'); + Alertify.debuggerInputArgsDialog( + gettext('Debugger'), args, restart_debug + ).resizeTo('60%', '60%'); }; return res; -}); \ No newline at end of file +}); diff --git a/web/pgadmin/tools/debugger/static/js/direct.js b/web/pgadmin/tools/debugger/static/js/direct.js index d0dbad7..0796d54 100644 --- a/web/pgadmin/tools/debugger/static/js/direct.js +++ b/web/pgadmin/tools/debugger/static/js/direct.js @@ -2,10 +2,10 @@ define([ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'pgadmin.alertifyjs', 'sources/pgadmin', 'pgadmin.browser', 'backbone', 'pgadmin.backgrid', 'pgadmin.backform', 'sources/../bundle/codemirror', - 'pgadmin.tools.debugger.ui', 'wcdocker', + 'pgadmin.tools.debugger.ui', 'sources/keyboard_shortcuts', 'wcdocker' ], function( gettext, url_for, $, _, Alertify, pgAdmin, pgBrowser, Backbone, Backgrid, - Backform, codemirror, debug_function_again + Backform, codemirror, debug_function_again, keyboardShortcuts ) { var CodeMirror = codemirror.default, @@ -31,7 +31,8 @@ define([ /* Function to set the breakpoint and send the line no. which is set to server - trans_id :- Unique Transaction ID, line_no - line no. to set the breakpoint, set_type = 0 - clear , 1 - set + trans_id :- Unique Transaction ID, line_no - line no. to set the breakpoint, + set_type = 0 - clear , 1 - set */ set_breakpoint: function(trans_id, line_no, set_type) { // Make ajax call to set/clear the break point by user @@ -57,7 +58,8 @@ define([ }); }, - // Function to get the latest breakpoint information and update the gutters of codemirror + // Function to get the latest breakpoint information and update the + // gutters of codemirror UpdateBreakpoint: function(trans_id) { var self = this; @@ -223,7 +225,8 @@ define([ // Call function to create and update local variables self.AddLocalVariables(res.data.result); self.AddParameters(res.data.result); - // If debug function is restarted then again start listener to read the updated messages. + // If debug function is restarted then again start listener to + // read the updated messages. if (pgTools.DirectDebug.debug_restarted) { if (pgTools.DirectDebug.debug_type) { self.poll_end_execution_result(trans_id); @@ -281,8 +284,8 @@ define([ }, /* - poll the actual result after user has executed the "continue", "step-into", "step-over" actions and get the - other updated information from the server. + poll the actual result after user has executed the "continue", "step-into", + "step-over" actions and get the other updated information from the server. */ poll_result: function(trans_id) { var self = this; @@ -299,8 +302,9 @@ define([ poll_timeout; /* - During the execution we should poll the result in minimum seconds but once the execution is completed - and wait for the another debugging session then we should decrease the polling frequency. + During the execution we should poll the result in minimum seconds but + once the execution is completed and wait for the another debugging + session then we should decrease the polling frequency. */ if (pgTools.DirectDebug.polling_timeout_idle) { // Poll the result after 1 second @@ -333,8 +337,13 @@ define([ pgTools.DirectDebug.docker.finishLoading(50); pgTools.DirectDebug.editor.setValue(res.data.result[0].src); self.UpdateBreakpoint(trans_id); - pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); - pgTools.DirectDebug.editor.addLineClass((res.data.result[0].linenumber - 2), 'wrap', 'CodeMirror-activeline-background'); + pgTools.DirectDebug.editor.removeLineClass( + self.active_line_no, 'wrap', 'CodeMirror-activeline-background' + ); + pgTools.DirectDebug.editor.addLineClass( + (res.data.result[0].linenumber - 2), + 'wrap', 'CodeMirror-activeline-background' + ); self.active_line_no = (res.data.result[0].linenumber - 2); // Update the stack, local variables and parameters information @@ -343,7 +352,9 @@ define([ } else if (!pgTools.DirectDebug.debug_type && !pgTools.DirectDebug.first_time_indirect_debug) { pgTools.DirectDebug.docker.finishLoading(50); if (self.active_line_no != undefined) { - pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); + pgTools.DirectDebug.editor.removeLineClass( + self.active_line_no, 'wrap', 'CodeMirror-activeline-background' + ); } self.clear_all_breakpoint(trans_id); self.execute_query(trans_id); @@ -358,8 +369,13 @@ define([ self.UpdateBreakpoint(trans_id); } - pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); - pgTools.DirectDebug.editor.addLineClass((res.data.result[0].linenumber - 2), 'wrap', 'CodeMirror-activeline-background'); + pgTools.DirectDebug.editor.removeLineClass( + self.active_line_no, 'wrap', 'CodeMirror-activeline-background' + ); + pgTools.DirectDebug.editor.addLineClass( + (res.data.result[0].linenumber - 2), + 'wrap', 'CodeMirror-activeline-background' + ); self.active_line_no = (res.data.result[0].linenumber - 2); // Update the stack, local variables and parameters information @@ -378,7 +394,9 @@ define([ pgTools.DirectDebug.polling_timeout_idle = true; // If status is Busy then poll the result by recursive call to the poll function if (!pgTools.DirectDebug.debug_type) { - pgTools.DirectDebug.docker.startLoading(gettext('Waiting for another session to invoke the target...')); + pgTools.DirectDebug.docker.startLoading( + gettext('Waiting for another session to invoke the target...') + ); // As we are waiting for another session to invoke the target,disable all the buttons self.enable('stop', false); @@ -429,8 +447,9 @@ define([ }, /* - For the direct debugging, we need to check weather the functions execution is completed or not. After completion - of the debugging, we will stop polling the result until new execution starts. + For the direct debugging, we need to check weather the functions execution + is completed or not. After completion of the debugging, we will stop polling + the result until new execution starts. */ poll_end_execution_result: function(trans_id) { var self = this; @@ -470,10 +489,13 @@ define([ if (res.data.status === 'Success') { if (res.data.result == undefined) { /* - "result" is undefined only in case of EDB procedure. As Once the EDB procedure execution is completed - then we are not getting any result so we need ignore the result. + "result" is undefined only in case of EDB procedure. + As Once the EDB procedure execution is completed then we are + not getting any result so we need ignore the result. */ - pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); + pgTools.DirectDebug.editor.removeLineClass( + self.active_line_no, 'wrap', 'CodeMirror-activeline-background' + ); pgTools.DirectDebug.direct_execution_completed = true; pgTools.DirectDebug.polling_timeout_idle = true; @@ -488,7 +510,8 @@ define([ // remove progress cursor $('.debugger-container').removeClass('show_progress'); - // Execution completed so disable the buttons other than "Continue/Start" button because user can still + // Execution completed so disable the buttons other than + // "Continue/Start" button because user can still // start the same execution again. self.enable('stop', false); self.enable('step_over', false); @@ -501,7 +524,9 @@ define([ } else { // Call function to create and update local variables .... if (res.data.result != null) { - pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); + pgTools.DirectDebug.editor.removeLineClass( + self.active_line_no, 'wrap', 'CodeMirror-activeline-background' + ); self.AddResults(res.data.col_info, res.data.result); pgTools.DirectDebug.results_panel.focus(); pgTools.DirectDebug.direct_execution_completed = true; @@ -518,7 +543,8 @@ define([ // remove progress cursor $('.debugger-container').removeClass('show_progress'); - // Execution completed so disable the buttons other than "Continue/Start" button because user can still + // Execution completed so disable the buttons other than + // "Continue/Start" button because user can still // start the same execution again. self.enable('stop', false); self.enable('step_over', false); @@ -532,7 +558,8 @@ define([ } } } else if (res.data.status === 'Busy') { - // If status is Busy then poll the result by recursive call to the poll function + // If status is Busy then poll the result by recursive call to + // the poll function self.poll_end_execution_result(trans_id); // Update the message tab of the debugger if (res.data.status_message) { @@ -545,9 +572,12 @@ define([ ); } else if (res.data.status === 'ERROR') { pgTools.DirectDebug.direct_execution_completed = true; - pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); + pgTools.DirectDebug.editor.removeLineClass( + self.active_line_no, 'wrap', 'CodeMirror-activeline-background' + ); - //Set the Alertify message to inform the user that execution is completed with error. + //Set the Alertify message to inform the user that execution is + // completed with error. if (!pgTools.DirectDebug.is_user_aborted_debugging) { Alertify.error(res.info, 3); } @@ -625,14 +655,16 @@ define([ } /* - Need to check if restart debugging really require to open the input dialog ? - If yes then we will get the previous arguments from database and populate the input dialog - If no then we should directly start the listener. + Need to check if restart debugging really require to open the input + dialog? If yes then we will get the previous arguments from database + and populate the input dialog, If no then we should directly start the + listener. */ if (res.data.result.require_input) { debug_function_again(res.data.result, restart_dbg); } else { - // Debugging of void function is started again so we need to start the listener again + // Debugging of void function is started again so we need to start + // the listener again var baseUrl = url_for('debugger.start_listener', { 'trans_id': trans_id, }); @@ -803,7 +835,9 @@ define([ success: function(res) { if (res.data.status) { // Call function to create and update local variables .... - pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); + pgTools.DirectDebug.editor.removeLineClass( + self.active_line_no, 'wrap', 'CodeMirror-activeline-background' + ); pgTools.DirectDebug.direct_execution_completed = true; pgTools.DirectDebug.is_user_aborted_debugging = true; @@ -1099,8 +1133,10 @@ define([ result_grid.render(); // Render the result grid into result panel - pgTools.DirectDebug.results_panel.$container.find('.debug_results').append(result_grid.el); - + pgTools.DirectDebug.results_panel + .$container + .find('.debug_results') + .append(result_grid.el); }, AddLocalVariables: function(result) { @@ -1120,11 +1156,13 @@ define([ }, }); - // Collection which contains the model for function informations. + // Collection which contains the model for function information. var VariablesCollection = Backbone.Collection.extend({ model: DebuggerVariablesModel, }); + VariablesCollection.prototype.on('change', self.deposit_parameter_value, self); + var gridCols = [{ name: 'name', label: gettext('Name'), @@ -1170,7 +1208,10 @@ define([ variable_grid.render(); // Render the variables grid into local variables panel - pgTools.DirectDebug.local_variables_panel.$container.find('.local_variables').append(variable_grid.el); + pgTools.DirectDebug.local_variables_panel + .$container + .find('.local_variables') + .append(variable_grid.el); }, @@ -1331,7 +1372,7 @@ define([ controller about the click and controller will take the action for the specified button click. */ var DebuggerToolbarView = Backbone.View.extend({ - el: '#btn-toolbar', + el: '.dubugger_main_container', initialize: function() { controller.on('pgDebugger:button:state:stop', this.enable_stop, this); controller.on('pgDebugger:button:state:step_over', this.enable_step_over, this); @@ -1347,6 +1388,7 @@ define([ 'click .btn-continue': 'on_continue', 'click .btn-step-over': 'on_step_over', 'click .btn-step-into': 'on_step_into', + 'keydown': 'keyAction', }, enable_stop: function(enable) { var $btn = this.$el.find('.btn-stop'); @@ -1414,7 +1456,6 @@ define([ $btn.attr('disabled', 'disabled'); } }, - on_stop: function() { controller.Stop(pgTools.DirectDebug.trans_id); }, @@ -1433,19 +1474,35 @@ define([ on_step_into: function() { controller.Step_into(pgTools.DirectDebug.trans_id); }, + keyAction: function (event) { + debugger; + var trans_id = pgTools.DirectDebug.trans_id, + $el = this.$el, + $input, panel_id, actual_panel, panel_content; + + panel_id = keyboardShortcuts.processEventDebugger( + controller, trans_id, $el, event + ); + + // Panel navigation + if(!_.isUndefined(panel_id) && !_.isNull(panel_id)) { + actual_panel = panel_id + 1; + pgTools.DirectDebug.docker.findPanels()[actual_panel].focus(); + } + }, }); /* - Function is responsible to create the new wcDocker instance for debugger and initialize the debugger panel inside - the docker instance. + Function is responsible to create the new wcDocker instance for debugger and + initialize the debugger panel inside the docker instance. */ var DirectDebug = function() {}; _.extend(DirectDebug.prototype, { - init: function(trans_id, debug_type) { /* We should get the transaction id from the server during initialization here */ + /* We should get the transaction id from the server during initialization here */ + init: function(trans_id, debug_type) { // We do not want to initialize the module multiple times. - var self = this; _.bindAll(pgTools.DirectDebug, 'messages'); @@ -1524,7 +1581,8 @@ define([ this.intializePanels(); }, - // Read the messages of the database server and get the port ID and attach the executer to that port. + // Read the messages of the database server and get the port ID and attach + // the executer to that port. messages: function(trans_id) { var self = this; // Make ajax call to listen the database message @@ -1615,7 +1673,7 @@ define([ height: '100%', isCloseable: false, isPrivate: true, - content: '
', + content: '
', }); // Create the Local variables panel to display the local variables of the function. @@ -1626,7 +1684,7 @@ define([ height: '100%', isCloseable: false, isPrivate: true, - content: '
', + content: '
', }); // Create the messages panel to display the message returned from the database server @@ -1637,7 +1695,7 @@ define([ height: '100%', isCloseable: false, isPrivate: true, - content: '
', + content: '
', }); // Create the result panel to display the result after debugging the function @@ -1648,7 +1706,7 @@ define([ height: '100%', isCloseable: false, isPrivate: true, - content: '
', + content: '
', }); // Create the stack pane panel to display the debugging stack information. @@ -1659,7 +1717,7 @@ define([ height: '100%', isCloseable: false, isPrivate: true, - content: '
', + content: '
', }); // Load all the created panels @@ -1671,34 +1729,50 @@ define([ }); self.code_editor_panel = self.docker.addPanel('code', wcDocker.DOCK.TOP); - self.parameters_panel = self.docker.addPanel( - 'parameters', wcDocker.DOCK.BOTTOM, self.code_editor_panel); - self.local_variables_panel = self.docker.addPanel('local_variables', wcDocker.DOCK.STACKED, self.parameters_panel, { + 'parameters', wcDocker.DOCK.BOTTOM, self.code_editor_panel + ); + self.local_variables_panel = self.docker.addPanel( + 'local_variables', + wcDocker.DOCK.STACKED, + self.parameters_panel, { tabOrientation: wcDocker.TAB.TOP, }); - self.messages_panel = self.docker.addPanel('messages', wcDocker.DOCK.STACKED, self.parameters_panel); + self.messages_panel = self.docker.addPanel( + 'messages', wcDocker.DOCK.STACKED, self.parameters_panel + ); self.results_panel = self.docker.addPanel( - 'results', wcDocker.DOCK.STACKED, self.parameters_panel); + 'results', wcDocker.DOCK.STACKED, self.parameters_panel + ); self.stack_pane_panel = self.docker.addPanel( - 'stack_pane', wcDocker.DOCK.STACKED, self.parameters_panel); + 'stack_pane', wcDocker.DOCK.STACKED, self.parameters_panel + ); - var editor_pane = $('
'); - var code_editor_area = $('').append(editor_pane); + var editor_pane = $('
'); + var code_editor_area = $('').append(editor_pane); self.code_editor_panel.layout().addItem(code_editor_area); // To show the line-number and set breakpoint marker details by user. self.editor = CodeMirror.fromTextArea( code_editor_area.get(0), { + tabindex: 0, lineNumbers: true, foldOptions: { widget: '\u2026', }, foldGutter: { - rangeFinder: CodeMirror.fold.combine(CodeMirror.pgadminBeginRangeFinder, CodeMirror.pgadminIfRangeFinder, - CodeMirror.pgadminLoopRangeFinder, CodeMirror.pgadminCaseRangeFinder), + rangeFinder: CodeMirror.fold.combine( + CodeMirror.pgadminBeginRangeFinder, + CodeMirror.pgadminIfRangeFinder, + CodeMirror.pgadminLoopRangeFinder, + CodeMirror.pgadminCaseRangeFinder + ), }, - gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'breakpoints'], + gutters: [ + 'CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'breakpoints' + ], mode: 'text/x-pgsql', readOnly: true, extraKeys: pgAdmin.Browser.editor_shortcut_keys, @@ -1741,7 +1815,7 @@ define([ panel.title(title); panel.closeable(false); panel.layout().addItem( - $('
', { + $('
', { 'class': 'pg-debugger-panel', }) ); diff --git a/web/pgadmin/tools/debugger/templates/debugger/direct.html b/web/pgadmin/tools/debugger/templates/debugger/direct.html index 29bb729..0e24d49 100644 --- a/web/pgadmin/tools/debugger/templates/debugger/direct.html +++ b/web/pgadmin/tools/debugger/templates/debugger/direct.html @@ -35,44 +35,57 @@ try { .debugger-container .wcLoadingIcon.fa-pulse{-webkit-animation: none;} {% endif %} - -
+ +
+
{% endblock %} - {% block css_link %} {% for stylesheet in stylesheets %}